package com.oa.handler;

import com.oa.common.enums.CodeStatus;
import com.oa.common.enums.UserStatus;
import com.oa.common.handler.SpringApplicationHolder;
import com.oa.common.utils.EncryptUtils;
import com.oa.common.vo.Propal;
import com.oa.entities.User;
import com.oa.service.RSAService;
import com.oa.service.RedisService;
import com.oa.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @name shiro权限的实现类
 * @author Yang
 * @date 2018-06-12
 * @version 1.0.1
 */
@Component("authRealm")
public class AuthRealm extends AuthorizingRealm {

    private static final Logger logger= LoggerFactory.getLogger(AuthRealm.class);

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.error("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
        String username  = (String) principals.getPrimaryPrincipal();
        UserService userService= SpringApplicationHolder.getBean(UserService.class);
        User user= userService.findByUsername(username);
        if (user!=null){
            List<String> authorities= userService.findById(user.getId());
            if (authorities != null) {
                SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
                authorizationInfo.addStringPermissions(authorities);
                return authorizationInfo;
            }
        }
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        AuthenticationTonken authenticationTonken= (AuthenticationTonken)token;
        String username= authenticationTonken.getUsername();
        String password= new String(authenticationTonken.getPassword());
        logger.warn("<---- shiro登录输入的用户名:"+username+" --->");
        logger.warn("<---- shiro登录传人的密码:"+password+" ---->");
        String code= authenticationTonken.getCode();
        logger.warn("<-- shiro获取到的验证码:"+code+" --->");
        RSAService rsaService= SpringApplicationHolder.getBean(RSAService.class);
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        password= rsaService.RSADecrypt(password,request);
        password=EncryptUtils.encodeMD5(password);
        authenticationTonken.setPassword(password.toCharArray());
        System.out.println(token.getCredentials());
        RedisService redisService= SpringApplicationHolder.getBean("redisServiceImpl",RedisService.class);
        //校验验证码是否合法
        if (!redisService.validateVerify(request.getSession().getId(), code)) {
            throw new UnknownAccountException(String.valueOf(CodeStatus.VERIFY_FAIL.getCode()));
        }
        //通过username从数据库中查找 User对象，如果找到，没找到.
        //实际项目中，这里可以根据实际情况做缓存，如果不做，Shiro自己也是有时间间隔机制，2分钟内不会重复执行该方法
        UserService userService= SpringApplicationHolder.getBean(UserService.class);
        User userInfo = userService.findByUsername(username);
        System.out.println("----->>userInfo="+userInfo);
        if(userInfo == null){
            throw new UnknownAccountException(String.valueOf(CodeStatus.MEMBER_UNDERFIND.getCode()));
        }
        if (!userInfo.getPassword().equals(password)){
            throw  new UnknownAccountException(String.valueOf(CodeStatus.PASSWORD_FAIL.getCode()));
        }
        if (!userInfo.getManager()) {
            if (userInfo.getInfo() != null) {
                if (userInfo.getInfo().getUserStatus() == UserStatus.DIMISSION.getCode()) {
                    throw new UnknownAccountException(String.valueOf(CodeStatus.USER_DISMISSION.getCode()));
                }
            }
        }
        userInfo.setLoginTime(System.currentTimeMillis());
        userInfo.setLoginIp(request.getLocalAddr());
        userService.update(userInfo);
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo.getUsername(), //用户名CredentialsMatcher
                userInfo.getPassword(), //密码
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }
}
